def aa_array_generation(beamlet_array_pts, spacing, phase_mask_size, additive_term=0.5, wavelength=800):
'''
This function uses an Additive Adaptive algorithm to compute the phase mask
to do an array of beamlets about the center of the mask. The source for this
method is:
http://physics.nyu.edu/grierlab/cgh3c/
However, this algorithm is not optimized because it should only take ~8
iterations to reach convergence but still produces a viable diffraction
grating.
:param (tuple) beamlet_array_pts: Describes the beamlet array you want to make of beamlets. The beamlets
will automatically be around the center
:param spacing: the spacing between each beamlet (in pixels)
:param additive_term: The amount of our target phase that gets added to the non-target phase. Higher means
that the target phase is used more
:param wavelength: The wavelength of your laser light
'''
k = 2*np.pi /(wavelength)
# Create the Target Array
target_array = np.zeros([phase_mask_size,phase_mask_size])
x_coors, y_coors = np.meshgrid((np.arange(0,beamlet_array_pts[0])*spacing-int(0.5*(beamlet_array_pts[0]-1)*spacing)),
(np.arange(0,beamlet_array_pts[1])*spacing-int(0.5*(beamlet_array_pts[1]-1)*spacing)))
x_coors += phase_mask_size/2
y_coors += phase_mask_size/2
#pdb.set_trace()
target_array[x_coors.flatten(), y_coors.flatten()] = 1
# Use a Guassian Kernel (fwh 3/4s of phase mask size) and random phase
# to produce the initial electric field
init_phase = (-np.pi - np.pi) * np.random.rand(phase_mask_size, phase_mask_size) + np.pi
init_amp = makeGaussian(phase_mask_size,phase_mask_size*3/4.0)
init_complex = init_amp * (np.cos(init_phase) + 1j*np.sin(init_phase))
image_plane = np.fft.fft2(make_complex_phase_amp(init_amp, init_phase))
# Set initial chi and error before loop
error_prev = None
chi = 10**10
while chi > 10**-6:
# Extract Amp and Phase from Image Plane
image_plane_amp = np.fft.fftshift(abs(image_plane))
image_plane_phase = np.angle(image_plane)
# Calculate Error and check if complete
error_curr = (np.sum(target_array -
image_plane_amp)**2)/phase_mask_size**2
if error_prev == None:
error_prev = error_curr
else:
chi = abs(error_curr - error_prev)/error_curr
#print chi
error_prev = error_curr
if chi < 10**(-6):
break
# Mix the image plane amplitude with the target amplitude
new_image_plane_amp = additive_term*normalize_array(target_array) + (1-additive_term)*normalize_array(image_plane_amp)
# Compute the E Field in the SLM Plane
slm_plane = np.fft.ifft2(make_complex_phase_amp(np.fft.fftshift(new_image_plane_amp), image_plane_phase))
slm_plane_amp = np.abs(slm_plane)
slm_plane_phase = np.angle(slm_plane)
# Compute the E Field in the Image plane, replace amplitude in SLM plane
# with gaussian
image_plane = np.fft.fft2(make_complex_phase_amp(init_amp, slm_plane_phase))
plt.figure(figsize=(10,10))
plt.subplot(221)
plt.title('Image Plane Amp')
plt.imshow(np.abs(image_plane_amp), cmap='gray', interpolation='none')
plt.gca().invert_yaxis()
plt.subplot(222)
plt.title('SLM Plane Amp')
plt.imshow(slm_plane_amp, cmap='gray', interpolation='none')
plt.subplot(223)
plt.title('Image Plane Phase')
plt.imshow(image_plane_phase, cmap='gray', interpolation='none')
plt.subplot(224)
plt.title('SLM Plane Phase')
plt.imshow(slm_plane_phase, cmap='gray', interpolation='none')
plt.tight_layout()
plt.show()
return slm_plane_phase, image_plane_amp